package com.dingding.transfer.stamper.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.dingding.transfer.stamper.constant.Code;
import com.dingding.transfer.stamper.constant.DingDingUrl;
import com.dingding.transfer.stamper.constant.TempletePara;
import com.dingding.transfer.stamper.dto.*;
import com.dingding.transfer.stamper.entity.CompInfo;
import com.dingding.transfer.stamper.entity.UseStampRecord;
import com.dingding.transfer.stamper.service.BusinessService;
import com.dingding.transfer.stamper.service.CallBackService;
import com.dingding.transfer.stamper.service.DingDingService;
import com.dingding.transfer.stamper.util.GsonUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiReportCreateRequest;
import com.dingtalk.api.response.OapiReportCreateResponse;
import com.google.gson.reflect.TypeToken;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wangxiyuan
 * @description
 * @createDate 2021/3/30 17:06
 **/
@Service
@Slf4j
public class DingDingServiceImpl implements DingDingService {
    @Autowired
    private CallBackService callBackService;

    @Autowired
    private BusinessService businessService;


    @Override
    public List<DeptInfo> getDeptInfo(CompInfo compInfo,String deptId) {
        String url = getTokenUrl(compInfo.getAppKey(),compInfo.getAppSecret(),DingDingUrl.GET_DEPT_LIST);
        Map<String,Object> para = new HashMap<>();
        para.put("dept_id",deptId);
        para.put("cursor",0);
        para.put("size",100);
        String result = HttpUtil.post(url,para);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if("0".equals(jsonObject.getString("errcode"))){
            String deptList = jsonObject.getString("result");
            if(!"[]".equals(deptList)){
                return GsonUtil.fromJson(deptList,new TypeToken<List<DeptInfo>>(){}.getType());
            }
        }else{
            log.info("部门反馈信息为{}",result);
        }
        return null;
    }

   public List<UserInfo> getUserInfo(CompInfo compInfo,String deptId){
       String url = getTokenUrl(compInfo.getAppKey(),compInfo.getAppSecret(),DingDingUrl.GET_USER_LIST);
       Map<String,Object> para = new HashMap<>();
       para.put("dept_id",deptId);
       para.put("cursor",0);
       para.put("size",100);
       String result = HttpUtil.post(url,para);
       JSONObject jsonObject = JSONObject.parseObject(result);
       if("0".equals(jsonObject.getString("errcode"))){
           JSONObject userObject = JSONObject.parseObject(jsonObject.getString("result"));
           String userInfos = userObject.getString("list");
           if(!"[]".equals(userInfos)){
               return GsonUtil.fromJson(userInfos,new TypeToken<List<UserInfo>>(){}.getType());
           }
       }else{
           log.info("员工反馈信息为{}",result);
       }
       return null;
   }

    @Override
    public UserInfo getUserInfo(String corpId, String userId) {
        String dingUrl = getTokenUrl(corpId,DingDingUrl.GET_USER_INFO);
        Map<String,Object> para = new HashMap<>();
        para.put("userid",userId);
        String result = HttpUtil.get(dingUrl,para);
        return GsonUtil.fromJson(result,UserInfo.class);
    }

    @Override
    public JSONObject getInstanceInfo(String corpId,String processId) {
        String url = getTokenUrl(corpId,DingDingUrl.GET_INSTANCE_INFO);
        Map<String,Object> para = new HashMap<>();
        para.put("process_instance_id",processId);
        String result = HttpUtil.post(url,para);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if("0".equals(jsonObject.getString("errcode"))){
            return jsonObject;
        }else{
            log.info("审批实例反馈信息为{}",result);
            return null;
        }
    }

    @Override
    public List<FormComponent> getFormDetails(String corpId,String processId) {
        JSONObject instanceInfo = getInstanceInfo(corpId,processId);
        if(instanceInfo != null){
            JSONObject processInstance = JSONObject.parseObject(instanceInfo.getString("process_instance"));
            // 获取表单信息
            String formJson = processInstance.getString("form_component_values");
            List<FormComponent> formComponentList = GsonUtil.fromJson(formJson, new TypeToken<List<FormComponent>>() {
            }.getType());
            return formComponentList;
        }
        return null;
    }

    @Cacheable(value = "TEMPLETE_INFO",key = "#p0 + #p2",unless = "#result == null")
    @Override
    public TempleteInfo getTempleteInfo(String corpId,String userId, String templeteName) {
        String url = getTokenUrl(corpId,DingDingUrl.GET_INFO_TEMPLETE);
        Map<String,Object> para = new HashMap<>();
        para.put("userid",userId);
        para.put("template_name",templeteName);
        String result = HttpUtil.post(url,para);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if("0".equals(jsonObject.getString("errcode"))){
            TempleteInfo templeteInfo = GsonUtil.fromJson(jsonObject.getString("result"), TempleteInfo.class);
            return templeteInfo;
        }else{
            log.error("获取{}模板信息失败{}",templeteName,result);
            return null;
        }
    }

    @Override
    public BaseResult createInfo(CompInfo compInfo,TempleteInfo templeteInfo,String[] toUserIds,List<UseStampRecord> stampRecords) {
        List<TempleteInfo.FieldInfo> fields = templeteInfo.getFields();
        if(CollectionUtil.isEmpty(fields)){
            return BaseResultFactory.produceEmptyResult(Code.TEMPLETE_MISSING);
        }
        DingTalkClient client = new DefaultDingTalkClient(DingDingUrl.CREATE_INFO);
        OapiReportCreateRequest req = new OapiReportCreateRequest();
        OapiReportCreateRequest.OapiCreateReportParam createReportParam = new OapiReportCreateRequest.OapiCreateReportParam();
        List<OapiReportCreateRequest.OapiReportContentVo> content = new ArrayList<>();
        // stampRecords 按时间倒序排列，第一条为最近使用记录
        UseStampRecord useStampRecord = stampRecords.get(0);
        String fileUrl = stampRecords.stream().map(record -> {
            // [使用记录1](https://yunxi.qstamper.com/group1/default/20210407/14/48/0/2-224-0-0-0-1617778122802.jpg)
            return new StringBuilder("[记录").append(stampRecords.indexOf(record)).append("](").append(record.getFileUrl()).append(")");
        }).collect(Collectors.joining(" "));
        useStampRecord.setFileUrl(fileUrl);
        for (TempleteInfo.FieldInfo fieldInfo:
             fields) {
            OapiReportCreateRequest.OapiReportContentVo obj = new OapiReportCreateRequest.OapiReportContentVo();
            obj.setSort(fieldInfo.getSort());
            obj.setType(fieldInfo.getType());
            obj.setContentType("markdown");
            obj.setKey(fieldInfo.getFieldName());
            obj.setContent(TempletePara.getContent(fieldInfo.getFieldName(),useStampRecord));
            content.add(obj);
        }
        createReportParam.setToUserids(Arrays.asList(toUserIds.clone()));
        createReportParam.setContents(content);
        createReportParam.setTemplateId(templeteInfo.getId());
        createReportParam.setToChat(true);
        createReportParam.setDdFrom(TempletePara.DD_FORM);
        createReportParam.setUserid(templeteInfo.getUserid());
        req.setCreateReportParam(createReportParam);
        int i = 0;
        OapiReportCreateResponse rsp = new OapiReportCreateResponse();
        while (i++ < 4){
            try {
                rsp = client.execute(req, callBackService.getToken(compInfo.getAppKey(),compInfo.getAppSecret()));
                break;
            } catch (ApiException e) {
                log.error("报送审批记录失败，失败原因为{}",e.getMessage());
                try {
                    Thread.sleep(30000);
                } catch (InterruptedException interruptedException) {
                    log.error("中断异常{}",interruptedException.getMessage());
                }
            }
        }
        return BaseResultFactory.produceEmptyResult(Integer.parseInt(rsp.getErrorCode()),rsp.getErrmsg());
    }

    private String getTokenUrl(String corpId,String url){
        CompInfo compInfo = businessService.getCompInfo(corpId);
        String token = callBackService.getToken(compInfo.getAppKey(),compInfo.getAppSecret());
       StringBuffer buffer = new StringBuffer(url);
       buffer.append("?access_token=").append(token);
       return buffer.toString();
   }

    private String getTokenUrl(String appKey,String appSecert,String url){
        String token = callBackService.getToken(appKey,appSecert);
        StringBuffer buffer = new StringBuffer(url);
        buffer.append("?access_token=").append(token);
        return buffer.toString();
    }
}
